<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>JavaScript Stackful Coroutines 模拟</title>
    <style>
        * {
            box-sizing: border-box;
            margin: 0;
            padding: 0;
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
        }
        
        body {
            background: linear-gradient(135deg, #1a2a6c, #b21f1f, #1a2a6c);
            color: #fff;
            min-height: 100vh;
            padding: 20px;
            display: flex;
            flex-direction: column;
            align-items: center;
        }
        
        .container {
            max-width: 900px;
            width: 100%;
            background: rgba(0, 0, 0, 0.7);
            border-radius: 15px;
            padding: 30px;
            margin: 20px 0;
            box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
        }
        
        header {
            text-align: center;
            margin-bottom: 30px;
            padding-bottom: 20px;
            border-bottom: 2px solid #4a90e2;
        }
        
        h1 {
            font-size: 2.8rem;
            margin-bottom: 10px;
            color: #4a90e2;
            text-shadow: 0 0 10px rgba(74, 144, 226, 0.7);
        }
        
        .subtitle {
            font-size: 1.2rem;
            color: #a0c4ff;
            max-width: 700px;
            margin: 0 auto;
            line-height: 1.6;
        }
        
        .content {
            display: flex;
            flex-wrap: wrap;
            gap: 30px;
            margin-bottom: 30px;
        }
        
        .explanation {
            flex: 1;
            min-width: 300px;
            background: rgba(30, 30, 50, 0.8);
            padding: 25px;
            border-radius: 12px;
            border: 1px solid #4a90e2;
        }
        
        .explanation h2 {
            color: #4a90e2;
            margin-bottom: 15px;
            font-size: 1.8rem;
        }
        
        .explanation ul {
            padding-left: 20px;
            margin: 15px 0;
        }
        
        .explanation li {
            margin-bottom: 10px;
            line-height: 1.6;
        }
        
        .code-section {
            flex: 1;
            min-width: 300px;
        }
        
        .code-container {
            background: #1e1e2e;
            border-radius: 12px;
            overflow: hidden;
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);
        }
        
        .code-header {
            background: #2d2d4a;
            padding: 15px;
            display: flex;
            justify-content: space-between;
            align-items: center;
            border-bottom: 1px solid #4a90e2;
        }
        
        .code-header h2 {
            color: #a0c4ff;
            font-size: 1.5rem;
        }
        
        .run-btn {
            background: #4a90e2;
            color: white;
            border: none;
            padding: 8px 16px;
            border-radius: 5px;
            cursor: pointer;
            font-weight: bold;
            transition: all 0.3s;
        }
        
        .run-btn:hover {
            background: #2a70c0;
            transform: translateY(-2px);
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
        }
        
        .code-content {
            padding: 20px;
            font-family: 'Fira Code', monospace;
            font-size: 16px;
            line-height: 1.5;
            overflow-x: auto;
            max-height: 400px;
            overflow-y: auto;
        }
        
        pre {
            margin: 0;
            color: #f8f8f2;
        }
        
        .output {
            background: rgba(30, 30, 50, 0.8);
            border-radius: 12px;
            padding: 25px;
            border: 1px solid #4a90e2;
            margin-top: 20px;
        }
        
        .output h2 {
            color: #4a90e2;
            margin-bottom: 15px;
            font-size: 1.8rem;
        }
        
        .output-content {
            background: #1a1a2a;
            border-radius: 8px;
            padding: 20px;
            min-height: 150px;
            max-height: 300px;
            overflow-y: auto;
            font-family: 'Fira Code', monospace;
            white-space: pre-wrap;
            margin-top: 10px;
            border: 1px solid #4a90e2;
        }
        
        .coroutine {
            color: #50fa7b;
        }
        
        .yield {
            color: #ff79c6;
        }
        
        .comment {
            color: #6272a4;
        }
        
        .function {
            color: #ffb86c;
        }
        
        .highlight {
            background: rgba(255, 215, 0, 0.2);
            padding: 2px 4px;
            border-radius: 3px;
        }
        
        .footer {
            text-align: center;
            margin-top: 20px;
            padding-top: 20px;
            border-top: 1px solid #4a90e2;
            color: #a0c4ff;
            font-size: 0.9rem;
        }
        
        @media (max-width: 768px) {
            .content {
                flex-direction: column;
            }
            
            .explanation, .code-section {
                min-width: 100%;
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <header>
            <h1>JavaScript 模拟 Stackful Coroutines</h1>
            <p class="subtitle">使用生成器函数和自定义调度器实现类似协程的功能</p>
        </header>
        
        <div class="content">
            <div class="explanation">
                <h2>Stackful Coroutines 简介</h2>
                <p>Stackful coroutines 是拥有独立栈空间的协程，可以暂停和恢复执行，类似于轻量级线程。</p>
                
                <p>JavaScript 原生并不支持真正的 stackful coroutines，但我们可以使用生成器函数来模拟类似行为：</p>
                
                <ul>
                    <li>每个协程由生成器函数表示</li>
                    <li>使用 <span class="highlight">yield</span> 关键字暂停执行</li>
                    <li>自定义调度器管理协程的执行</li>
                    <li>协程可以嵌套调用其他协程</li>
                    <li>协程之间可以协作式切换</li>
                </ul>
                
                <p>在本示例中，我们实现了：</p>
                <ul>
                    <li>一个简单的协程调度器</li>
                    <li>多个协程示例：计数、数据处理、嵌套协程</li>
                    <li>模拟异步操作的协程</li>
                    <li>协程间协作式切换</li>
                </ul>
                
                <p>点击右侧的"运行示例"按钮查看协程执行过程</p>
            </div>
            
            <div class="code-section">
                <div class="code-container">
                    <div class="code-header">
                        <h2>Coroutine 实现代码</h2>
                        <button class="run-btn" id="runBtn">运行示例</button>
                    </div>
                    <div class="code-content">
                        <pre><code><span class="comment">// 协程调度器</span>
<span class="function">class</span> <span class="coroutine">CoroutineScheduler</span> {
    <span class="function">constructor</span>() {
        <span class="function">this</span>.coroutines = [];
        <span class="function">this</span>.running = false;
    }
    
    <span class="function">addCoroutine</span>(genFunc, ...args) {
        <span class="function">const</span> coroutine = genFunc(...args);
        <span class="function">this</span>.coroutines.push(coroutine);
        <span class="function">if</span> (!<span class="function">this</span>.running) {
            <span class="function">this</span>.run();
        }
    }
    
    <span class="function">async run</span>() {
        <span class="function">this</span>.running = true;
        <span class="function">while</span> (<span class="function">this</span>.coroutines.length > 0) {
            <span class="function">const</span> coroutine = <span class="function">this</span>.coroutines.shift();
            <span class="function">const</span> { value, done } = coroutine.next();
            
            <span class="function">if</span> (done) {
                <span class="function">this</span>.log(`Coroutine completed`);
            } <span class="function">else</span> {
                <span class="function">if</span> (value instanceof Promise) {
                    <span class="function">await</span> value;
                } <span class="function">else</span> {
                    <span class="function">await</span> <span class="function">new</span> Promise(resolve => setTimeout(resolve, 100));
                }
                <span class="function">this</span>.coroutines.push(coroutine);
            }
        }
        <span class="function">this</span>.running = false;
    }
    
    log(message) {
        <span class="function">const</span> output = document.getElementById('output');
        output.textContent += message + '\n';
        output.scrollTop = output.scrollHeight;
    }
}

<span class="comment">// 创建调度器实例</span>
<span class="function">const</span> scheduler = new CoroutineScheduler();

<span class="comment">// 示例协程函数</span>
<span class="function">function*</span> <span class="coroutine">counterCoroutine</span>(name, max) {
    <span class="function">for</span> (let i = 1; i <= max; i++) {
        scheduler.log(`${name}: ${i}`);
        <span class="yield">yield</span>; <span class="comment">// 暂停执行，让出控制权</span>
    }
    scheduler.log(`${name} finished!`);
}

<span class="function">function*</span> <span class="coroutine">dataProcessor</span>() {
    <span class="function">const</span> data = [10, 20, 30, 40, 50];
    <span class="function">let</span> sum = 0;
    
    <span class="function">for</span> (const item of data) {
        scheduler.log(`Processing data: ${item}`);
        sum += item;
        <span class="yield">yield</span>;
    }
    
    scheduler.log(`Data processed. Total sum: ${sum}`);
}

<span class="function">function*</span> <span class="coroutine">nestedCoroutine</span>() {
    scheduler.log('Starting nested coroutine');
    <span class="yield">yield</span>* counterCoroutine('Nested Counter', 3);
    scheduler.log('Nested coroutine completed');
}

<span class="function">function*</span> <span class="coroutine">asyncSimulation</span>() {
    scheduler.log('Starting async simulation...');
    <span class="yield">yield</span> <span class="function">new</span> Promise(resolve => setTimeout(resolve, 300));
    scheduler.log('Async step 1 completed');
    <span class="yield">yield</span> <span class="function">new</span> Promise(resolve => setTimeout(resolve, 300));
    scheduler.log('Async step 2 completed');
    scheduler.log('Async simulation finished');
}

<span class="comment">// 启动所有协程</span>
<span class="function">function</span> startCoroutines() {
    scheduler.addCoroutine(counterCoroutine, 'Coroutine A', 5);
    scheduler.addCoroutine(counterCoroutine, 'Coroutine B', 3);
    scheduler.addCoroutine(dataProcessor);
    scheduler.addCoroutine(nestedCoroutine);
    scheduler.addCoroutine(asyncSimulation);
}</code></pre>
                    </div>
                </div>
            </div>
        </div>
        
        <div class="output">
            <h2>协程执行输出</h2>
            <div id="output" class="output-content">点击"运行示例"查看协程输出...</div>
        </div>
        
        <div class="footer">
            <p>注意：这是使用 JavaScript 生成器模拟的 stackful coroutines，并非真正的系统级协程实现</p>
        </div>
    </div>

    <script>
        // 协程调度器
        class CoroutineScheduler {
            constructor() {
                this.coroutines = [];
                this.running = false;
            }
            
            addCoroutine(genFunc, ...args) {
                const coroutine = genFunc(...args);
                this.coroutines.push(coroutine);
                if (!this.running) {
                    this.run();
                }
            }
        
            async run() {
                this.running = true;
                while (this.coroutines.length > 0) {
                    const coroutine = this.coroutines.shift();
                    const { value, done } = coroutine.next();
                    
                    if (done) {
                        this.log(`Coroutine completed`);
                    } else {
                        if (value instanceof Promise) {
                            await value;
                        } else {
                            await new Promise(resolve => setTimeout(resolve, 100));
                        }
                        this.coroutines.push(coroutine);
                    }
                }
                this.running = false;
            }
            
            log(message) {
                const output = document.getElementById('output');
                output.textContent += message + '\n';
                output.scrollTop = output.scrollHeight;
            }
        }
        
        // 创建调度器实例
        const scheduler = new CoroutineScheduler();
        
        // 示例协程函数
        function* counterCoroutine(name, max) {
            for (let i = 1; i <= max; i++) {
                scheduler.log(`${name}: ${i}`);
                yield; // 暂停执行，让出控制权
            }
            scheduler.log(`${name} finished!`);
        }
        
        function* dataProcessor() {
            const data = [10, 20, 30, 40, 50];
            let sum = 0;
            
            for (const item of data) {
                scheduler.log(`Processing data: ${item}`);
                sum += item;
                yield;
            }
            
            scheduler.log(`Data processed. Total sum: ${sum}`);
        }
        
        function* nestedCoroutine() {
            scheduler.log('Starting nested coroutine');
            yield* counterCoroutine('Nested Counter', 3);
            scheduler.log('Nested coroutine completed');
        }
        
        function* asyncSimulation() {
            scheduler.log('Starting async simulation...');
            yield new Promise(resolve => setTimeout(resolve, 300));
            scheduler.log('Async step 1 completed');
            yield new Promise(resolve => setTimeout(resolve, 300));
            scheduler.log('Async step 2 completed');
            scheduler.log('Async simulation finished');
        }
        
        // 启动所有协程
        function startCoroutines() {
            scheduler.addCoroutine(counterCoroutine, 'Coroutine A', 5);
            scheduler.addCoroutine(counterCoroutine, 'Coroutine B', 3);
            scheduler.addCoroutine(dataProcessor);
            scheduler.addCoroutine(nestedCoroutine);
            scheduler.addCoroutine(asyncSimulation);
        }
        
        // 绑定按钮事件
        document.getElementById('runBtn').addEventListener('click', () => {
            const output = document.getElementById('output');
            output.textContent = 'Starting coroutines...\n';
            startCoroutines();
        });
    </script>
</body>
</html>